home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / ibus-table / engine / table.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-10-28  |  43KB  |  1,293 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __all__ = ('tabengine',)
  5. import os
  6. import ibus
  7. from ibus import keysyms
  8. from ibus import modifier
  9. from ibus import ascii
  10. import tabdict
  11. import re
  12. patt_edit = re.compile('(.*)###(.*)###(.*)')
  13. patt_uncommit = re.compile('(.*)@@@(.*)')
  14. from gettext import dgettext
  15.  
  16. _ = lambda a: dgettext('ibus-table', a)
  17.  
  18. N_ = lambda a: a
  19. import dbus
  20.  
  21. class KeyEvent:
  22.     
  23.     def __init__(self, keyval, is_press, state):
  24.         self.code = keyval
  25.         self.mask = state
  26.         if not is_press:
  27.             self.mask |= modifier.RELEASE_MASK
  28.         
  29.  
  30.     
  31.     def __str__(self):
  32.         return '%s 0x%08x' % (keysyms.keycode_to_name(self.code), self.mask)
  33.  
  34.  
  35.  
  36. class editor(object):
  37.     '''Hold user inputs chars and preedit string'''
  38.     
  39.     def __init__(self, phrase_table_index, valid_input_chars, max_key_length, database, parser = tabdict.parse, deparser = tabdict.deparse, max_length = 64):
  40.         self.db = database
  41.         self._pt = phrase_table_index
  42.         self._parser = parser
  43.         self._deparser = deparser
  44.         self._max_key_len = int(max_key_length)
  45.         self._max_length = max_length
  46.         self._valid_input_chars = valid_input_chars
  47.         self._chars = [
  48.             [],
  49.             [],
  50.             []]
  51.         self._t_chars = []
  52.         self._u_chars = []
  53.         self._tabkey_list = []
  54.         self._strings = []
  55.         self._cursor = [
  56.             0,
  57.             0]
  58.         self._candidates = [
  59.             [],
  60.             []]
  61.         self._lookup_table = ibus.LookupTable(tabengine._page_size)
  62.         self._py_mode = False
  63.         self._zi = u''
  64.         self._caret = 0
  65.         self._onechar = False
  66.         self._chinese_mode = self.get_chinese_mode()
  67.  
  68.     
  69.     def get_chinese_mode(self):
  70.         '''Use LC_CTYPE in your box to determine the _chinese_mode'''
  71.         
  72.         try:
  73.             if os.environ.has_key('LC_CTYPE'):
  74.                 _editor__lc = os.environ['LC_CTYPE'].split('.')[0].lower()
  75.             else:
  76.                 _editor__lc = os.environ['LANG'].split('.')[0].lower()
  77.             if _editor__lc.find('zh_') == 0:
  78.                 _editor__place = _editor__lc.split('_')[1]
  79.                 if _editor__place == 'cn':
  80.                     return 0
  81.                 return 1
  82.             _editor__lc.find('zh_') == 0
  83.             if self.db._is_chinese():
  84.                 return 0
  85.             return -1
  86.         except:
  87.             return -1
  88.  
  89.  
  90.     
  91.     def change_chinese_mode(self):
  92.         if self._chinese_mode != -1:
  93.             self._chinese_mode = (self._chinese_mode + 1) % 5
  94.         
  95.  
  96.     
  97.     def clear(self):
  98.         '''Remove data holded'''
  99.         self.over_input()
  100.         self._t_chars = []
  101.         self._strings = []
  102.         self._cursor = [
  103.             0,
  104.             0]
  105.         self._py_mode = False
  106.         self._zi = u''
  107.         self.update_candidates
  108.  
  109.     
  110.     def is_empty(self):
  111.         return len(self._t_chars) == 0
  112.  
  113.     
  114.     def clear_input(self):
  115.         '''
  116.         Remove input characters held for Table mode,
  117.         '''
  118.         self._chars = [
  119.             [],
  120.             [],
  121.             []]
  122.         self._tabkey_list = []
  123.         self._lookup_table.clean()
  124.         self._lookup_table.show_cursor(False)
  125.         self._candidates = [
  126.             [],
  127.             []]
  128.  
  129.     
  130.     def over_input(self):
  131.         '''
  132.         Remove input characters held for Table mode,
  133.         '''
  134.         self.clear_input()
  135.         self._u_chars = []
  136.  
  137.     
  138.     def set_parser(self, parser):
  139.         '''change input parser'''
  140.         self.clear()
  141.         self._parser = parser
  142.  
  143.     
  144.     def add_input(self, c):
  145.         '''add input character'''
  146.         if len(self._t_chars) == self._max_length:
  147.             return True
  148.         self._zi = u''
  149.         if self._cursor[1]:
  150.             self.split_phrase()
  151.         
  152.         if (len(self._chars[0]) == self._max_key_len or not (self._py_mode) or len(self._chars[0]) == 7) and self._py_mode:
  153.             self.auto_commit_to_preedit()
  154.             res = self.add_input(c)
  155.             return res
  156.         if self._chars[1]:
  157.             self._chars[1].append(c)
  158.         elif (not (self._py_mode) or c in self._valid_input_chars or self._py_mode) and c in u'abcdefghijklmnopqrstuvwxyz!@#$%':
  159.             
  160.             try:
  161.                 self._tabkey_list += self._parser(c)
  162.                 self._chars[0].append(c)
  163.             self._chars[1].append(c)
  164.  
  165.         else:
  166.             self._chars[1].append(c)
  167.         self._t_chars.append(c)
  168.         res = self.update_candidates()
  169.         return res
  170.  
  171.     
  172.     def pop_input(self):
  173.         '''remove and display last input char held'''
  174.         _c = ''
  175.         if self._chars[1]:
  176.             _c = self._chars[1].pop()
  177.         elif self._chars[0]:
  178.             _c = self._chars[0].pop()
  179.             self._tabkey_list.pop()
  180.             if not self._chars[0] and self._u_chars:
  181.                 self._chars[0] = self._u_chars.pop()
  182.                 self._chars[1] = self._chars[1][:-1]
  183.                 self._tabkey_list = self._parser(self._chars[0])
  184.                 self._strings.pop(self._cursor[0] - 1)
  185.                 self._cursor[0] -= 1
  186.             
  187.         
  188.         self._t_chars.pop()
  189.         self.update_candidates()
  190.         return _c
  191.  
  192.     
  193.     def get_input_chars(self):
  194.         '''get characters held, valid and invalid'''
  195.         return self._chars[0] + self._chars[1]
  196.  
  197.     
  198.     def get_input_chars_string(self):
  199.         '''Get valid input char string'''
  200.         return u''.join(map(str, self._t_chars))
  201.  
  202.     
  203.     def get_all_input_strings(self):
  204.         '''Get all uncommit input characters, used in English mode or direct commit'''
  205.         return u''.join(map(u''.join, self._u_chars + [
  206.             self._chars[0]] + [
  207.             self._chars[1]]))
  208.  
  209.     
  210.     def get_index(self, key):
  211.         '''Get the index of key in database table'''
  212.         return self._pt.index(key)
  213.  
  214.     
  215.     def split_phrase(self):
  216.         '''Splite current phrase into two phrase'''
  217.         _head = u''
  218.         _end = u''
  219.         
  220.         try:
  221.             _head = self._strings[self._cursor[0]][:self._cursor[1]]
  222.             _end = self._strings[self._cursor[0]][self._cursor[1]:]
  223.             self._strings.pop(self._cursor[0])
  224.             self._strings.insert(self._cursor[0], _head)
  225.             self._strings.insert(self._cursor[0] + 1, _end)
  226.             self._cursor[0] += 1
  227.             self._cursor[1] = 0
  228.         except:
  229.             pass
  230.  
  231.  
  232.     
  233.     def remove_before_string(self):
  234.         '''Remove string before cursor'''
  235.         if self._cursor[1] != 0:
  236.             self.split_phrase()
  237.         
  238.         if self._cursor[0] > 0:
  239.             self._strings.pop(self._cursor[0] - 1)
  240.             self._cursor[0] -= 1
  241.         
  242.         if self._cursor == [
  243.             0,
  244.             0]:
  245.             self._t_chars = []
  246.         
  247.  
  248.     
  249.     def remove_after_string(self):
  250.         '''Remove string after cursor'''
  251.         if self._cursor[1] != 0:
  252.             self.split_phrase()
  253.         
  254.         if self._cursor[0] >= len(self._strings):
  255.             pass
  256.         else:
  257.             self._strings.pop(self._cursor[0])
  258.  
  259.     
  260.     def remove_before_char(self):
  261.         '''Remove character before cursor'''
  262.         if self._cursor[1] > 0:
  263.             _str = self._strings[self._cursor[0]]
  264.             self._strings[self._cursor[0]] = _str[:self._cursor[1] - 1] + _str[self._cursor[1]:]
  265.             self._cursor[1] -= 1
  266.         elif self._cursor[0] == 0:
  267.             pass
  268.         elif len(self._strings[self._cursor[0] - 1]) == 1:
  269.             self.remove_before_string()
  270.         else:
  271.             self._strings[self._cursor[0] - 1] = self._strings[self._cursor[0] - 1][:-1]
  272.         if self._cursor == [
  273.             0,
  274.             0]:
  275.             self._t_chars = []
  276.         
  277.  
  278.     
  279.     def remove_after_char(self):
  280.         '''Remove character after cursor'''
  281.         if self._cursor[1] == 0:
  282.             if self._cursor[0] == len(self._strings):
  283.                 pass
  284.             elif len(self._strings[self._cursor[0]]) == 1:
  285.                 self.remove_after_string()
  286.             else:
  287.                 self._strings[self._cursor[0]] = self._strings[self._cursor[0]][1:]
  288.         elif self._cursor[1] + 1 == len(self._strings[self._cursor[0]]):
  289.             self.split_phrase()
  290.             self.remove_after_string()
  291.         else:
  292.             string = self._strings[self._cursor[0]]
  293.             self._strings[self._cursor[0]] = string[:self._cursor[1]] + string[self._cursor[1] + 1:]
  294.  
  295.     
  296.     def get_invalid_input_chars(self):
  297.         '''get invalid characters held'''
  298.         return self._chars[1]
  299.  
  300.     
  301.     def get_invalid_input_string(self):
  302.         '''get invalid characters in string form'''
  303.         return u''.join(self._chars[1])
  304.  
  305.     
  306.     def get_preedit_strings(self):
  307.         '''Get preedit strings'''
  308.         if self._candidates[0]:
  309.             if self._py_mode:
  310.                 _p_index = 8
  311.             else:
  312.                 _p_index = self.get_index('phrase')
  313.             _candi = u'###' + self._candidates[0][int(self._lookup_table.get_cursor_pos())][_p_index] + u'###'
  314.         else:
  315.             input_chars = self.get_input_chars()
  316.             if input_chars:
  317.                 _candi = u''.join([
  318.                     '###'] + map(str, input_chars) + [
  319.                     '###'])
  320.             else:
  321.                 _candi = u''
  322.         if self._strings:
  323.             res = u''
  324.             _cursor = self._cursor[0]
  325.             _luc = len(self._u_chars)
  326.             if _luc:
  327.                 if not _candi == u'' or u'######':
  328.                     pass
  329.                 _candi = _candi
  330.                 res = u''.join(self._strings[:_cursor - _luc] + [
  331.                     u'@@@'] + self._strings[_cursor - _luc:_cursor] + [
  332.                     _candi] + self._strings[_cursor:])
  333.             else:
  334.                 res = u''.join(self._strings[:_cursor] + [
  335.                     _candi] + self._strings[_cursor:])
  336.             return res
  337.         return _candi
  338.  
  339.     
  340.     def add_caret(self, addstr):
  341.         '''add length to caret position'''
  342.         self._caret += len(addstr)
  343.  
  344.     
  345.     def get_caret(self):
  346.         '''Get caret position in preedit strings'''
  347.         self._caret = 0
  348.         if self._cursor[0] and self._strings:
  349.             map(self.add_caret, self._strings[:self._cursor[0]])
  350.         
  351.         self._caret += self._cursor[1]
  352.         self._caret += len(_candi)
  353.         return self._caret
  354.  
  355.     
  356.     def arrow_left(self):
  357.         '''Process Arrow Left Key Event.
  358.         Update cursor data when move caret left'''
  359.         if self.get_preedit_strings():
  360.             if not self.get_input_chars() or self._u_chars:
  361.                 if self._cursor[1] > 0:
  362.                     self._cursor[1] -= 1
  363.                 elif self._cursor[0] > 0:
  364.                     self._cursor[1] = len(self._strings[self._cursor[0] - 1]) - 1
  365.                     self._cursor[0] -= 1
  366.                 else:
  367.                     self._cursor[0] = len(self._strings)
  368.                     self._cursor[1] = 0
  369.                 self.update_candidates()
  370.             
  371.             return True
  372.         return False
  373.  
  374.     
  375.     def arrow_right(self):
  376.         '''Process Arrow Right Key Event.
  377.         Update cursor data when move caret right'''
  378.         if self.get_preedit_strings():
  379.             if not self.get_input_chars() or self._u_chars:
  380.                 if self._cursor[1] == 0:
  381.                     if self._cursor[0] == len(self._strings):
  382.                         self._cursor[0] = 0
  383.                     else:
  384.                         self._cursor[1] += 1
  385.                 else:
  386.                     self._cursor[1] += 1
  387.                 if self._cursor[1] == len(self._strings[self._cursor[0]]):
  388.                     self._cursor[0] += 1
  389.                     self._cursor[1] = 0
  390.                 
  391.                 self.update_candidates()
  392.             
  393.             return True
  394.         return False
  395.  
  396.     
  397.     def control_arrow_left(self):
  398.         '''Process Control + Arrow Left Key Event.
  399.         Update cursor data when move caret to string left'''
  400.         if self.get_preedit_strings():
  401.             if not self.get_input_chars() or self._u_chars:
  402.                 if self._cursor[1] == 0:
  403.                     if self._cursor[0] == 0:
  404.                         self._cursor[0] = len(self._strings) - 1
  405.                     else:
  406.                         self._cursor[0] -= 1
  407.                 else:
  408.                     self._cursor[1] = 0
  409.                 self.update_candidates()
  410.             
  411.             return True
  412.         return False
  413.  
  414.     
  415.     def control_arrow_right(self):
  416.         '''Process Control + Arrow Right Key Event.
  417.         Update cursor data when move caret to string right'''
  418.         if self.get_preedit_strings():
  419.             if not self.get_input_chars() or self._u_chars:
  420.                 if self._cursor[1] == 0:
  421.                     if self._cursor[0] == len(self._strings):
  422.                         self._cursor[0] = 1
  423.                     else:
  424.                         self._cursor[0] += 1
  425.                 else:
  426.                     self._cursor[0] += 1
  427.                     self._cursor[1] = 0
  428.                 self.update_candidates()
  429.             
  430.             return True
  431.         return False
  432.  
  433.     
  434.     def ap_candidate(self, candi):
  435.         '''append candidate to lookup_table'''
  436.         if not self._py_mode:
  437.             _p_index = self.get_index('phrase')
  438.             _fkey = self.get_index('m0')
  439.         else:
  440.             _p_index = 8
  441.             _fkey = 1
  442.         if self.db._is_chinese:
  443.             _tbks = u''.join(map(self._deparser, candi[_fkey + len(self._tabkey_list):_p_index - 1]))
  444.             if self._py_mode:
  445.                 _tbks = _tbks.replace('!', '\xe2\x86\x911').replace('@', '\xe2\x86\x912').replace('#', '\xe2\x86\x913').replace('$', '\xe2\x86\x914').replace('%', '\xe2\x86\x915')
  446.             
  447.         else:
  448.             _tbks = u''.join(map(self._deparser, candi[_fkey + len(self._tabkey_list):_p_index]))
  449.         _phrase = candi[_p_index]
  450.         attrs = ibus.AttrList()
  451.         attrs.append(ibus.AttributeForeground(1668002, 0, len(_phrase) + len(_tbks)))
  452.         if candi[-2] < 0:
  453.             attrs.append(ibus.AttributeForeground(7798979, 0, len(_phrase)))
  454.         elif candi[-1] > 0:
  455.             attrs.append(ibus.AttributeForeground(0, 0, len(_phrase)))
  456.         else:
  457.             attrs.append(ibus.AttributeForeground(0, 0, len(_phrase)))
  458.         self._lookup_table.append_candidate(ibus.Text(_phrase + _tbks, attrs))
  459.         self._lookup_table.show_cursor(False)
  460.  
  461.     
  462.     def filter_candidates(self, candidates):
  463.         '''Filter candidates if IME is Chinese'''
  464.         if self._chinese_mode not in (2, 3):
  465.             return candidates[:]
  466.         bm_index = self._pt.index('category')
  467.         if self._chinese_mode == 2:
  468.             return (filter,)((lambda x: x[bm_index] & 1), candidates) + (filter,)((lambda x: if x[bm_index] & 2:
  469. passnot (x[bm_index] & 1)), candidates) + (filter,)((lambda x: x[bm_index] & 4), candidates)
  470.         if self._chinese_mode == 3:
  471.             return (filter,)((lambda x: x[bm_index] & 2), candidates) + (filter,)((lambda x: if x[bm_index] & 1:
  472. passnot (x[bm_index] & 2)), candidates) + (filter,)((lambda x: x[bm_index] & 4), candidates)
  473.  
  474.     
  475.     def update_candidates(self):
  476.         '''Update lookuptable'''
  477.         if self._chars[0] == self._chars[2] or self._candidates[0] or self._chars[1]:
  478.             pass
  479.         else:
  480.             only_one_last = self.one_candidate()
  481.             self._lookup_table.clean()
  482.             self._lookup_table.show_cursor(False)
  483.             if self._tabkey_list:
  484.                 if not self._py_mode:
  485.                     if self.db._is_chinese:
  486.                         bm_index = self._pt.index('category')
  487.                         if self._chinese_mode == 0:
  488.                             self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar, 1)
  489.                         elif self._chinese_mode == 1:
  490.                             self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar, 2)
  491.                         else:
  492.                             self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar)
  493.                     else:
  494.                         self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar)
  495.                 else:
  496.                     self._candidates[0] = self.db.select_zi(self._tabkey_list)
  497.                 self._chars[2] = self._chars[0][:]
  498.             else:
  499.                 self._candidates[0] = []
  500.             if self._candidates[0]:
  501.                 self._candidates[0] = self.filter_candidates(self._candidates[0])
  502.             
  503.             if self._candidates[0]:
  504.                 map(self.ap_candidate, self._candidates[0])
  505.             elif self._chars[0]:
  506.                 if not self._chars[1]:
  507.                     if ascii.ispunct(self._chars[0][-1].encode('ascii')) and len(self._chars[0][:-1]) in self.db.pkeylens or only_one_last:
  508.                         if self._py_mode:
  509.                             if self._chars[0][-1] in '!@#$%':
  510.                                 self._chars[0].pop()
  511.                                 self._tabkey_list.pop()
  512.                                 return True
  513.                         
  514.                         if self._candidates[1]:
  515.                             self._candidates[0] = self._candidates[1]
  516.                             self._candidates[1] = []
  517.                             last_input = self.pop_input()
  518.                             self.auto_commit_to_preedit()
  519.                             res = self.add_input(last_input)
  520.                             return res
  521.                         self.pop_input()
  522.                         self._lookup_table.clean()
  523.                         self._lookup_table.show_cursor(False)
  524.                         return False
  525.                     only_one_last
  526.                     self._chars[1].append(self._chars[0].pop())
  527.                     self._tabkey_list.pop()
  528.                 
  529.                 self._candidates[0] = []
  530.             else:
  531.                 self._lookup_table.clean()
  532.                 self._lookup_table.show_cursor(False)
  533.             self._candidates[1] = self._candidates[0]
  534.         return True
  535.  
  536.     
  537.     def commit_to_preedit(self):
  538.         '''Add select phrase in lookup table to preedit string'''
  539.         if not self._py_mode:
  540.             _p_index = self.get_index('phrase')
  541.         else:
  542.             _p_index = 8
  543.         
  544.         try:
  545.             self._strings.insert(self._cursor[0], self._candidates[0][self.get_cursor_pos()][_p_index])
  546.             self._cursor[0] += 1
  547.             if self._py_mode:
  548.                 self._zi = self._candidates[0][self.get_cursor_pos()][_p_index]
  549.             
  550.             self.over_input()
  551.             self.update_candidates()
  552.         except:
  553.             pass
  554.  
  555.  
  556.     
  557.     def auto_commit_to_preedit(self):
  558.         '''Add select phrase in lookup table to preedit string'''
  559.         if not self._py_mode:
  560.             _p_index = self.get_index('phrase')
  561.         else:
  562.             _p_index = 8
  563.         
  564.         try:
  565.             self._u_chars.append(self._chars[0][:])
  566.             self._strings.insert(self._cursor[0], self._candidates[0][self.get_cursor_pos()][_p_index])
  567.             self._cursor[0] += 1
  568.             self.clear_input()
  569.             self.update_candidates()
  570.         except:
  571.             pass
  572.  
  573.  
  574.     
  575.     def get_aux_strings(self):
  576.         '''Get aux strings'''
  577.         input_chars = self.get_input_chars()
  578.         if input_chars:
  579.             aux_string = u''.join(self._chars[0])
  580.             if self._py_mode:
  581.                 aux_string = aux_string.replace('!', '1').replace('@', '2').replace('#', '3').replace('$', '4').replace('%', '5')
  582.             
  583.             return aux_string
  584.         aux_string = u''
  585.         if self._zi:
  586.             tabcodes = self.db.find_zi_code(self._zi)
  587.             aux_string = self._zi + u': '
  588.             aux_string = u' '.join(tabcodes)
  589.         
  590.         cstr = u''.join(self._strings)
  591.         if self.db.user_can_define_phrase:
  592.             if len(cstr) > 1:
  593.                 aux_string += u'\t#: ' + self.db.parse_phrase_to_tabkeys(cstr)
  594.             
  595.         
  596.         return aux_string
  597.  
  598.     
  599.     def arrow_down(self):
  600.         '''Process Arrow Down Key Event
  601.         Move Lookup Table cursor down'''
  602.         res = self._lookup_table.cursor_down()
  603.         self.update_candidates()
  604.         if not res and self._candidates[0]:
  605.             return True
  606.         return res
  607.  
  608.     
  609.     def arrow_up(self):
  610.         '''Process Arrow Up Key Event
  611.         Move Lookup Table cursor up'''
  612.         res = self._lookup_table.cursor_up()
  613.         self.update_candidates()
  614.         if not res and self._candidates[0]:
  615.             return True
  616.         return res
  617.  
  618.     
  619.     def page_down(self):
  620.         '''Process Page Down Key Event
  621.         Move Lookup Table page down'''
  622.         res = self._lookup_table.page_down()
  623.         self.update_candidates()
  624.         if not res and self._candidates[0]:
  625.             return True
  626.         return res
  627.  
  628.     
  629.     def page_up(self):
  630.         '''Process Page Up Key Event
  631.         move Lookup Table page up'''
  632.         res = self._lookup_table.page_up()
  633.         self.update_candidates()
  634.         if not res and self._candidates[0]:
  635.             return True
  636.         return res
  637.  
  638.     
  639.     def number(self, index):
  640.         '''Select the candidates in Lookup Table
  641.         index should start from 0'''
  642.         self._lookup_table.set_cursor_pos_in_current_page(index)
  643.         if index != self._lookup_table.get_cursor_pos_in_current_page():
  644.             return False
  645.         self.commit_to_preedit()
  646.         return True
  647.  
  648.     
  649.     def alt_number(self, index):
  650.         '''Remove the candidates in Lookup Table from user_db index should start from 0'''
  651.         cps = self._lookup_table.get_current_page_start()
  652.         pos = cps + index
  653.         if len(self._candidates[0]) > pos:
  654.             can = self._candidates[0][pos]
  655.             if can[-2] < 0:
  656.                 self.db.remove_phrase(can)
  657.                 self._chars[2].pop()
  658.                 self.update_candidates()
  659.             
  660.             return True
  661.         return False
  662.  
  663.     
  664.     def get_cursor_pos(self):
  665.         '''get lookup table cursor position'''
  666.         return self._lookup_table.get_cursor_pos()
  667.  
  668.     
  669.     def get_lookup_table(self):
  670.         '''Get lookup table'''
  671.         return self._lookup_table
  672.  
  673.     
  674.     def is_lt_visible(self):
  675.         '''Check whether lookup table is visible'''
  676.         return self._lookup_table.is_cursor_visible()
  677.  
  678.     
  679.     def backspace(self):
  680.         '''Process backspace Key Event'''
  681.         self._zi = u''
  682.         if self.get_input_chars():
  683.             self.pop_input()
  684.             return True
  685.         if self.get_preedit_strings():
  686.             self.remove_before_char()
  687.             return True
  688.         return False
  689.  
  690.     
  691.     def control_backspace(self):
  692.         '''Process control+backspace Key Event'''
  693.         self._zi = u''
  694.         if self.get_input_chars():
  695.             self.over_input()
  696.             return True
  697.         if self.get_preedit_strings():
  698.             self.remove_before_string()
  699.             return True
  700.         return False
  701.  
  702.     
  703.     def delete(self):
  704.         '''Process delete Key Event'''
  705.         self._zi = u''
  706.         if self.get_input_chars():
  707.             return True
  708.         if self.get_preedit_strings():
  709.             self.remove_after_char()
  710.             return True
  711.         return False
  712.  
  713.     
  714.     def control_delete(self):
  715.         '''Process control+delete Key Event'''
  716.         self._zi = u''
  717.         if self.get_input_chars():
  718.             return True
  719.         if self.get_preedit_strings():
  720.             self.remove_after_string()
  721.             return True
  722.         return False
  723.  
  724.     
  725.     def l_shift(self):
  726.         '''Process Left Shift Key Event as immediately commit to preedit strings'''
  727.         if self._chars[0]:
  728.             self.commit_to_preedit()
  729.             return True
  730.         return False
  731.  
  732.     
  733.     def r_shift(self):
  734.         '''Proess Right Shift Key Event as changed between PinYin Mode and Table Mode'''
  735.         self._zi = u''
  736.         if self._chars[0]:
  737.             self.commit_to_preedit()
  738.         
  739.         self._py_mode = not (self._py_mode)
  740.         return True
  741.  
  742.     
  743.     def space(self):
  744.         '''Process space Key Event
  745.         return (KeyProcessResult,whethercommit,commitstring)'''
  746.         if self._chars[1]:
  747.             return (False, u'')
  748.         if self._t_chars:
  749.             istr = self.get_all_input_strings()
  750.             self.commit_to_preedit()
  751.             pstr = self.get_preedit_strings()
  752.             self.clear()
  753.             return (True, pstr, istr)
  754.         return (False, u'', u'')
  755.  
  756.     
  757.     def one_candidate(self):
  758.         '''Return true if there is only one candidate'''
  759.         return len(self._candidates[0]) == 1
  760.  
  761.  
  762.  
  763. class tabengine(ibus.EngineBase):
  764.     '''The IM Engine for Tables'''
  765.     _page_size = 6
  766.     
  767.     def __init__(self, bus, obj_path, db):
  768.         super(tabengine, self).__init__(bus, obj_path)
  769.         self._lookup_table = ibus.LookupTable(tabengine._page_size)
  770.         self.db = db
  771.         self._parser = tabdict.parse
  772.         self._icon_dir = '%s%s%s%s' % (os.getenv('IBUS_TABLE_LOCATION'), os.path.sep, 'icons', os.path.sep)
  773.         self._mode = 1
  774.         self._ime_py = self.db.get_ime_property('pinyin_mode')
  775.         if self._ime_py:
  776.             if self._ime_py.lower() == u'true':
  777.                 self._ime_py = True
  778.             else:
  779.                 self._ime_py = False
  780.         else:
  781.             print 'We coult not find "pinyin_mode" entry in database, is it a outdated database?'
  782.             self._ime_py = False
  783.         self._status = self.db.get_ime_property('status_prompt').encode('utf8')
  784.         self._chars = self.db.get_ime_property('valid_input_chars')
  785.         self._valid_input_chars = []
  786.         for _c in self._chars:
  787.             if _c in tabdict.tab_key_list:
  788.                 self._valid_input_chars.append(_c)
  789.                 continue
  790.         
  791.         del self._chars
  792.         self._pt = self.db.get_phrase_table_index()
  793.         self._ml = int(self.db.get_ime_property('max_key_length'))
  794.         self._editor = editor(self._pt, self._valid_input_chars, self._ml, self.db)
  795.         self._prev_key = None
  796.         self._prev_char = None
  797.         self._double_quotation_state = False
  798.         self._single_quotation_state = False
  799.         self._full_width_letter = [
  800.             False,
  801.             self.db.get_ime_property('def_full_width_letter').lower() == u'true']
  802.         self._full_width_punct = [
  803.             False,
  804.             self.db.get_ime_property('def_full_width_punct').lower() == u'true']
  805.         
  806.         try:
  807.             self._auto_commit = self.db.get_ime_property('auto_commit').lower() == u'true'
  808.         except:
  809.             self._auto_commit = False
  810.  
  811.         self._len_list = [
  812.             0]
  813.         
  814.         try:
  815.             bus = dbus.SessionBus()
  816.             user = os.path.basename(os.path.expanduser('~'))
  817.             self._sm_bus = bus.get_object('org.ibus.table.SpeedMeter.%s' % user, '/org/ibus/table/SpeedMeter')
  818.             self._sm = dbus.Interface(self._sm_bus, 'org.ibus.table.SpeedMeter')
  819.         except:
  820.             self._sm = None
  821.  
  822.         self._sm_on = False
  823.         self._on = False
  824.         self.reset()
  825.  
  826.     
  827.     def reset(self):
  828.         self._editor.clear()
  829.         self._double_quotation_state = False
  830.         self._single_quotation_state = False
  831.         self._prev_key = None
  832.         self._init_properties()
  833.         self._update_ui()
  834.  
  835.     
  836.     def do_destroy(self):
  837.         self.reset()
  838.         self.focus_out()
  839.         super(tabengine, self).do_destroy()
  840.  
  841.     
  842.     def _init_properties(self):
  843.         self.properties = ibus.PropList()
  844.         self._status_property = ibus.Property(u'status')
  845.         if self.db._is_chinese:
  846.             self._cmode_property = ibus.Property(u'cmode')
  847.         
  848.         self._letter_property = ibus.Property(u'letter')
  849.         self._punct_property = ibus.Property(u'punct')
  850.         self._py_property = ibus.Property(u'py_mode')
  851.         self._onechar_property = ibus.Property(u'onechar')
  852.         self._auto_commit_property = ibus.Property(u'acommit')
  853.         for prop in (self._status_property, self._letter_property, self._punct_property, self._py_property, self._onechar_property, self._auto_commit_property):
  854.             self.properties.append(prop)
  855.         
  856.         if self.db._is_chinese:
  857.             self.properties.insert(1, self._cmode_property)
  858.         
  859.         self.register_properties(self.properties)
  860.         self._refresh_properties()
  861.  
  862.     
  863.     def _refresh_properties(self):
  864.         '''Method used to update properties'''
  865.         if self._mode == 1:
  866.             if self._status == u'CN':
  867.                 self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'chinese.svg'))
  868.                 self._status_property.set_label(_(u'CN'))
  869.             else:
  870.                 self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'ibus-table.svg'))
  871.                 self._status_property.set_label(self._status)
  872.             self._status_property.set_tooltip(_(u'Switch to English mode'))
  873.         else:
  874.             self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'english.svg'))
  875.             self._status_property.set_label(_(u'EN'))
  876.             self._status_property.set_tooltip(_(u'Switch to Table mode'))
  877.         if self._full_width_letter[self._mode]:
  878.             self._letter_property.set_icon(u'%s%s' % (self._icon_dir, 'full-letter.svg'))
  879.             self._letter_property.set_tooltip(_(u'Switch to half letter'))
  880.         else:
  881.             self._letter_property.set_icon(u'%s%s' % (self._icon_dir, 'half-letter.svg'))
  882.             self._letter_property.set_tooltip(_(u'Switch to full letter'))
  883.         if self._full_width_punct[self._mode]:
  884.             self._punct_property.set_icon(u'%s%s' % (self._icon_dir, 'full-punct.svg'))
  885.             self._punct_property.set_tooltip(_(u'Switch to half punction'))
  886.         else:
  887.             self._punct_property.set_icon(u'%s%s' % (self._icon_dir, 'half-punct.svg'))
  888.             self._punct_property.set_tooltip(_(u'Switch to full punction'))
  889.         if self._editor._py_mode:
  890.             self._py_property.set_icon(u'%s%s' % (self._icon_dir, 'py-mode.svg'))
  891.             self._py_property.set_tooltip(_(u'Switch to Table mode'))
  892.         else:
  893.             self._py_property.set_icon(u'%s%s' % (self._icon_dir, 'tab-mode.svg'))
  894.             self._py_property.set_tooltip(_(u'Switch to PinYin mode'))
  895.         if self._editor._onechar:
  896.             self._onechar_property.set_icon(u'%s%s' % (self._icon_dir, 'onechar.svg'))
  897.             self._onechar_property.set_tooltip(_(u'Switch to phrase mode'))
  898.         else:
  899.             self._onechar_property.set_icon(u'%s%s' % (self._icon_dir, 'phrase.svg'))
  900.             self._onechar_property.set_tooltip(_(u'Switch to single char mode'))
  901.         if self._auto_commit:
  902.             self._auto_commit_property.set_icon(u'%s%s' % (self._icon_dir, 'acommit.svg'))
  903.             self._auto_commit_property.set_tooltip(_(u'Switch to normal commit mode, which use space to commit'))
  904.         else:
  905.             self._auto_commit_property.set_icon(u'%s%s' % (self._icon_dir, 'ncommit.svg'))
  906.             self._auto_commit_property.set_tooltip(_(u'Switch to direct commit mode'))
  907.         if self.db._is_chinese:
  908.             if self._editor._chinese_mode == 0:
  909.                 self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'sc-mode.svg'))
  910.                 self._cmode_property.set_tooltip(_(u'Switch to Traditional Chinese mode'))
  911.             elif self._editor._chinese_mode == 1:
  912.                 self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'tc-mode.svg'))
  913.                 self._cmode_property.set_tooltip(_(u'Switch to Simplify Chinese first Big Charset Mode'))
  914.             elif self._editor._chinese_mode == 2:
  915.                 self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'scb-mode.svg'))
  916.                 self._cmode_property.set_tooltip(_(u'Switch to Traditional Chinese first Big Charset Mode'))
  917.             elif self._editor._chinese_mode == 3:
  918.                 self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'tcb-mode.svg'))
  919.                 self._cmode_property.set_tooltip(_(u'Switch to Big Charset Mode'))
  920.             elif self._editor._chinese_mode == 4:
  921.                 self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'cb-mode.svg'))
  922.                 self._cmode_property.set_tooltip(_(u'Switch to Simplify Chinese Mode'))
  923.             
  924.         
  925.         map(self.update_property, self.properties)
  926.  
  927.     
  928.     def _change_mode(self):
  929.         '''Shift input mode, TAB -> EN -> TAB
  930.         '''
  931.         self._mode = int(not (self._mode))
  932.         self.reset()
  933.         self._update_ui()
  934.  
  935.     
  936.     def property_activate(self, property, prop_state = ibus.PROP_STATE_UNCHECKED):
  937.         '''Shift property'''
  938.         if property == u'status':
  939.             self._change_mode()
  940.         elif property == u'py_mode' and self._ime_py:
  941.             self._editor.r_shift()
  942.         elif property == u'onechar':
  943.             self._editor._onechar = not (self._editor._onechar)
  944.         elif property == u'acommit':
  945.             self._auto_commit = not (self._auto_commit)
  946.         elif property == u'letter':
  947.             self._full_width_letter[self._mode] = not self._full_width_letter[self._mode]
  948.         elif property == u'punct':
  949.             self._full_width_punct[self._mode] = not self._full_width_punct[self._mode]
  950.         elif property == u'cmode':
  951.             self._editor.change_chinese_mode()
  952.             self.reset()
  953.         
  954.         self._refresh_properties()
  955.  
  956.     
  957.     def _update_preedit(self):
  958.         '''Update Preedit String in UI'''
  959.         _str = self._editor.get_preedit_strings()
  960.         if _str == u'':
  961.             super(tabengine, self).update_preedit_text(ibus.Text(u'', None), 0, False)
  962.         else:
  963.             attrs = ibus.AttrList()
  964.             res = patt_edit.match(_str)
  965.             if res:
  966.                 _str = u''
  967.                 ures = patt_uncommit.match(res.group(1))
  968.                 if ures:
  969.                     _str = u''.join(ures.groups())
  970.                     lc = len(ures.group(1))
  971.                     lu = len(ures.group(2))
  972.                     attrs.append(ibus.AttributeForeground(1785603, 0, lc))
  973.                     attrs.append(ibus.AttributeForeground(562594, lc, lu))
  974.                     lg1 = len(_str)
  975.                 else:
  976.                     _str += res.group(1)
  977.                     lg1 = len(res.group(1))
  978.                     attrs.append(ibus.AttributeForeground(1785603, 0, lg1))
  979.                 _str += res.group(2)
  980.                 _str += res.group(3)
  981.                 lg2 = len(res.group(2))
  982.                 lg3 = len(res.group(3))
  983.                 attrs.append(ibus.AttributeForeground(921248, lg1, lg2))
  984.                 attrs.append(ibus.AttributeForeground(1785603, lg1 + lg2, lg3))
  985.             else:
  986.                 attrs.append(ibus.AttributeForeground(1785603, 0, len(_str)))
  987.             attrs = ibus.AttrList()
  988.             attrs.append(ibus.AttributeUnderline(ibus.ATTR_UNDERLINE_SINGLE, 0, len(_str)))
  989.             super(tabengine, self).update_preedit_text(ibus.Text(_str, attrs), self._editor.get_caret(), True)
  990.  
  991.     
  992.     def _update_aux(self):
  993.         '''Update Aux String in UI'''
  994.         _ic = self._editor.get_aux_strings()
  995.         if _ic:
  996.             attrs = ibus.AttrList([
  997.                 ibus.AttributeForeground(9770421, 0, len(_ic))])
  998.             super(tabengine, self).update_auxiliary_text(ibus.Text(_ic, attrs), True)
  999.         else:
  1000.             self.hide_auxiliary_text()
  1001.  
  1002.     
  1003.     def _update_lookup_table(self):
  1004.         '''Update Lookup Table in UI'''
  1005.         if self._editor.is_empty():
  1006.             self.hide_lookup_table()
  1007.             return None
  1008.         self.update_lookup_table(self._editor.get_lookup_table(), True, True)
  1009.  
  1010.     
  1011.     def _update_ui(self):
  1012.         '''Update User Interface'''
  1013.         self._update_lookup_table()
  1014.         self._update_preedit()
  1015.         self._update_aux()
  1016.  
  1017.     
  1018.     def add_string_len(self, astring):
  1019.         if self._sm_on:
  1020.             
  1021.             try:
  1022.                 self._sm.Accumulate(len(astring))
  1023.  
  1024.         
  1025.  
  1026.     
  1027.     def commit_string(self, string):
  1028.         self._editor.clear()
  1029.         self._update_ui()
  1030.         super(tabengine, self).commit_text(ibus.Text(string))
  1031.         self._prev_char = string[-1]
  1032.  
  1033.     
  1034.     def _convert_to_full_width(self, c):
  1035.         '''convert half width character to full width'''
  1036.         return ibus.unichar_half_to_full(c)
  1037.  
  1038.     
  1039.     def _match_hotkey(self, key, code, mask):
  1040.         return False
  1041.  
  1042.     
  1043.     def process_key_event(self, keyval, keycode, state):
  1044.         '''Process Key Events
  1045.         Key Events include Key Press and Key Release,
  1046.         modifier means Key Pressed
  1047.         '''
  1048.         key = KeyEvent(keyval, state & modifier.RELEASE_MASK == 0, state)
  1049.         key.mask &= ~(modifier.MOD2_MASK)
  1050.         result = self._process_key_event(key)
  1051.         self._prev_key = key
  1052.         return result
  1053.  
  1054.     
  1055.     def _process_key_event(self, key):
  1056.         '''Internal method to process key event'''
  1057.         if not (self._editor._t_chars) and self._match_hotkey(key, keysyms.Shift_L, modifier.SHIFT_MASK + modifier.RELEASE_MASK):
  1058.             self._change_mode()
  1059.             return True
  1060.         if self._match_hotkey(key, keysyms.space, modifier.SHIFT_MASK):
  1061.             self.property_activate('letter')
  1062.             return True
  1063.         if self._match_hotkey(key, keysyms.period, modifier.CONTROL_MASK):
  1064.             self.property_activate('punct')
  1065.             return True
  1066.         if self._mode:
  1067.             return self._table_mode_process_key_event(key)
  1068.         return self._english_mode_process_key_event(key)
  1069.  
  1070.     
  1071.     def _english_mode_process_key_event(self, key):
  1072.         '''English Mode Process Key Event'''
  1073.         if key.mask & modifier.RELEASE_MASK:
  1074.             return True
  1075.         if key.code >= 128:
  1076.             return False
  1077.         if key.mask & modifier.CONTROL_MASK + modifier.ALT_MASK:
  1078.             return False
  1079.         c = unichr(key.code)
  1080.         if ascii.ispunct(key.code):
  1081.             if self._full_width_punct[self._mode]:
  1082.                 self.commit_string(self._convert_to_full_width(c))
  1083.                 return True
  1084.             self.commit_string(c)
  1085.             return True
  1086.         ascii.ispunct(key.code)
  1087.         if self._full_width_letter[self._mode]:
  1088.             self.commit_string(self._convert_to_full_width(c))
  1089.             return True
  1090.         self.commit_string(c)
  1091.         return True
  1092.         return False
  1093.  
  1094.     
  1095.     def _table_mode_process_key_event(self, key):
  1096.         '''Xingma Mode Process Key Event'''
  1097.         
  1098.         cond_letter_translate = lambda c: if self._full_width_letter[self._mode]:
  1099. self._convert_to_full_width(c)c
  1100.         
  1101.         cond_punct_translate = lambda c: if self._full_width_punct[self._mode]:
  1102. self._convert_to_full_width(c)c
  1103.         if self._match_hotkey(key, keysyms.Shift_R, modifier.SHIFT_MASK + modifier.RELEASE_MASK) and self._ime_py:
  1104.             res = self._editor.r_shift()
  1105.             self._refresh_properties()
  1106.             self._update_ui()
  1107.             return res
  1108.         if self._match_hotkey(key, keysyms.Shift_R, modifier.SHIFT_MASK + modifier.RELEASE_MASK) or self._match_hotkey(key, keysyms.Shift_L, modifier.SHIFT_MASK + modifier.RELEASE_MASK):
  1109.             res = self._editor.l_shift()
  1110.             self._update_ui()
  1111.             return res
  1112.         if self._match_hotkey(key, keysyms.comma, modifier.CONTROL_MASK):
  1113.             self.property_activate(u'onechar')
  1114.             return True
  1115.         if self._match_hotkey(key, keysyms.slash, modifier.CONTROL_MASK):
  1116.             self.property_activate(u'acommit')
  1117.             return True
  1118.         if self._match_hotkey(key, keysyms.semicolon, modifier.CONTROL_MASK):
  1119.             self.property_activate(u'cmode')
  1120.             return True
  1121.         if self._match_hotkey(key, keysyms.apostrophe, modifier.CONTROL_MASK):
  1122.             self._sm_on = not (self._sm_on)
  1123.             return True
  1124.         if key.mask & modifier.RELEASE_MASK:
  1125.             return True
  1126.         if key.code == keysyms.Escape:
  1127.             self.reset()
  1128.             self._update_ui()
  1129.             return True
  1130.         if key.code in (keysyms.Return, keysyms.KP_Enter):
  1131.             commit_string = self._editor.get_all_input_strings()
  1132.             self.commit_string(commit_string)
  1133.             return True
  1134.         if key.code in (keysyms.Down, keysyms.KP_Down):
  1135.             res = self._editor.arrow_down()
  1136.             self._update_ui()
  1137.             return res
  1138.         if key.code in (keysyms.Up, keysyms.KP_Up):
  1139.             res = self._editor.arrow_up()
  1140.             self._update_ui()
  1141.             return res
  1142.         if key.code in (keysyms.Left, keysyms.KP_Left) and key.mask & modifier.CONTROL_MASK:
  1143.             res = self._editor.control_arrow_left()
  1144.             self._update_ui()
  1145.             return res
  1146.         if key.code in (keysyms.Right, keysyms.KP_Right) and key.mask & modifier.CONTROL_MASK:
  1147.             res = self._editor.control_arrow_right()
  1148.             self._update_ui()
  1149.             return res
  1150.         if key.code in (keysyms.Left, keysyms.KP_Left):
  1151.             res = self._editor.arrow_left()
  1152.             self._update_ui()
  1153.             return res
  1154.         if key.code in (keysyms.Right, keysyms.KP_Right):
  1155.             res = self._editor.arrow_right()
  1156.             self._update_ui()
  1157.             return res
  1158.         if key.code == keysyms.BackSpace and key.mask & modifier.CONTROL_MASK:
  1159.             res = self._editor.control_backspace()
  1160.             self._update_ui()
  1161.             return res
  1162.         if key.code == keysyms.BackSpace:
  1163.             res = self._editor.backspace()
  1164.             self._update_ui()
  1165.             return res
  1166.         if key.code == keysyms.Delete and key.mask & modifier.CONTROL_MASK:
  1167.             res = self._editor.control_delete()
  1168.             self._update_ui()
  1169.             return res
  1170.         if key.code == keysyms.Delete:
  1171.             res = self._editor.delete()
  1172.             self._update_ui()
  1173.             return res
  1174.         if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0] and key.mask & modifier.CONTROL_MASK:
  1175.             res = self._editor.number(key.code - keysyms._1)
  1176.             self._update_ui()
  1177.             return res
  1178.         if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0] and key.mask & modifier.ALT_MASK:
  1179.             res = self._editor.alt_number(key.code - keysyms._1)
  1180.             self._update_ui()
  1181.             return res
  1182.         if key.code == keysyms.space:
  1183.             o_py = self._editor._py_mode
  1184.             sp_res = self._editor.space()
  1185.             if sp_res[0]:
  1186.                 self.commit_string(sp_res[1])
  1187.                 self.add_string_len(sp_res[1])
  1188.                 self.db.check_phrase(sp_res[1], sp_res[2])
  1189.             elif sp_res[1] == u' ':
  1190.                 self.commit_string(cond_letter_translate(u' '))
  1191.             
  1192.             return True
  1193.         if key.mask & modifier.CONTROL_MASK + modifier.ALT_MASK:
  1194.             return False
  1195.         if key.mask & modifier.ALT_MASK:
  1196.             return False
  1197.         if (unichr(key.code) in self._valid_input_chars or self._editor._py_mode) and unichr(key.code) in u'abcdefghijklmnopqrstuvwxyz!@#$%':
  1198.             if self._auto_commit:
  1199.                 pass
  1200.             res = self._editor.add_input(unichr(key.code))
  1201.             if not res:
  1202.                 sp_res = self._editor.space()
  1203.                 if sp_res[0]:
  1204.                     self.commit_string(sp_res[1] + key_char)
  1205.                     self.add_string_len(sp_res[1])
  1206.                     self.db.check_phrase(sp_res[1], sp_res[2])
  1207.                     return True
  1208.                 self.commit_string(key_char)
  1209.                 return True
  1210.             res
  1211.             if self._auto_commit and self._editor.one_candidate():
  1212.                 pass
  1213.             self._update_ui()
  1214.             return True
  1215.         if key.code in (keysyms.equal, keysyms.Page_Down, keysyms.KP_Page_Down) and self._editor._candidates[0]:
  1216.             res = self._editor.page_down()
  1217.             self._update_lookup_table()
  1218.             return res
  1219.         if key.code in (keysyms.minus, keysyms.Page_Up, keysyms.KP_Page_Up) and self._editor._candidates[0]:
  1220.             res = self._editor.page_up()
  1221.             self._update_lookup_table()
  1222.             return res
  1223.         if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0]:
  1224.             input_keys = self._editor.get_all_input_strings()
  1225.             res = self._editor.number(key.code - keysyms._1)
  1226.             return True
  1227.         if key.code <= 127:
  1228.             self._editor.clear()
  1229.             return True
  1230.         return False
  1231.  
  1232.     
  1233.     def focus_in(self):
  1234.         if self._on:
  1235.             self.register_properties(self.properties)
  1236.             self._refresh_properties()
  1237.             self._update_ui()
  1238.             
  1239.             try:
  1240.                 if self._sm_on:
  1241.                     self._sm.Show()
  1242.                 else:
  1243.                     self._sm.Hide()
  1244.  
  1245.         
  1246.  
  1247.     
  1248.     def focus_out(self):
  1249.         
  1250.         try:
  1251.             self._sm.Hide()
  1252.         except:
  1253.             pass
  1254.  
  1255.  
  1256.     
  1257.     def enable(self):
  1258.         
  1259.         try:
  1260.             self._sm.Reset()
  1261.         except:
  1262.             pass
  1263.  
  1264.         self._on = True
  1265.         self.focus_in()
  1266.  
  1267.     
  1268.     def disable(self):
  1269.         self.reset()
  1270.         
  1271.         try:
  1272.             self._sm.Hide()
  1273.         except:
  1274.             pass
  1275.  
  1276.         self._on = False
  1277.  
  1278.     
  1279.     def lookup_table_page_up(self):
  1280.         if self._editor.page_up():
  1281.             self._update_lookup_table()
  1282.             return True
  1283.         return True
  1284.  
  1285.     
  1286.     def lookup_table_page_down(self):
  1287.         if self._editor.page_down():
  1288.             self._update_lookup_table()
  1289.             return True
  1290.         return False
  1291.  
  1292.  
  1293.